/**
 * 
 */
package org.swing.utility.jdbc.thread;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author lqnhu
 *
 */
public class LoadablePool<T extends Loadable> {
	private static Logger logger = Logger.getLogger(LoadablePool.class
			.getName());
	LinkedBlockingDeque<T> pool = new LinkedBlockingDeque<T>();
	int sequence;
	int count = 0;
	int size;
	Class<T> clazz;

	public LoadablePool(int size, Class<T> clazz) {
		this.size = size;
		this.clazz = clazz;
	}

	public T getLoadable() throws Exception {
		T loadable = pool.poll();
		if (loadable == null) {
			if (count < size) {
				loadable = clazz.newInstance();
				loadable.pool = this;
				++count;
			} else {
				for (;;) {
					try {
						loadable = pool.take();
						break;
					} catch (InterruptedException ex) {
						logger.log(Level.WARNING, "getLoader interrupted", ex);
					}
				}
			}
		}
		loadable.sequence = sequence++;
		return loadable;
	}

	@SuppressWarnings("unchecked")
	public void putLoader(Loadable loadable) {
		for (;;) {
			try {
				// User a LIFO model to keep the hot objects in cache.
				pool.putFirst((T) loadable);
				break;
			} catch (InterruptedException ex) {
				logger.log(Level.WARNING, "putLoader interrupted!", ex);
			}
		}
	}
}